import * as THREE from 'three';
import { KongZhi } from './KongZhi.js'
import { sheZhi } from '../cunChu/bianLiang.js'
import { huanJing } from '../huanJing/HuanJing.js'
import { gengXinJiHe } from '../gengXin/gengXin.js'
import { wanJia } from '../changJing/wuTi/WanJia.js'

// 玩家视角默认快捷键
let moRenKuaiJieJian = {
	zhiZhenSuo: {
		miaoShu: '锁定指针后操作视角',
		kuaiJieJian: 'AltLeft'
	},
	qianJin: {
		miaoShu: '前进',
		kuaiJieJian: 'KeyW'
	},
	houTui: {
		miaoShu: '后退',
		kuaiJieJian: 'KeyS'
	},
	zuoYi: {
		miaoShu: '左移',
		kuaiJieJian: 'KeyA'
	},
	youYi: {
		miaoShu: '右移',
		kuaiJieJian: 'KeyD'
	},
	jiaSu: {
		miaoShu: '加速',
		kuaiJieJian: 'ShiftLeft'
	},
	tiao: {
		miaoShu: '跳',
		kuaiJieJian: 'Space'
	},
	dengKaiGuan: {
		miaoShu: '灯开关',
		kuaiJieJian: 'KeyP'
	}
}

Object.defineProperty(moRenKuaiJieJian, 'miaoShu', {
	value: '玩家控制',
	enumerable: false
})

let wanJiaKongZhi = null

class WanJiaKongZhi extends KongZhi {
	kuaiJieJianBianHao = 'WanJiaKongZhi'
	kuaiJieJian = null
	zhiZhenSuo = false
	xuanZhuanSuLv = 0.002 // 镜头旋转速率
	juLiZ = 5 // 镜头z轴距离
	zuiYuan = 10 // 镜头最远距离
	qian = 0
	hou = 0
	zuo = 0
	you = 0
	tiao = 0
	keTiao = true // 按下按键只能跳一次
	yiDongShiJian = -1 // 移动开始时间
	manSuShiJian = 0.2 // 按下移动键，正常速度之前的慢速时间
	yiSu = 5 // 移动速度
	tiaoSu = 5.5 // 跳初速度
	jiaSu = false // 加速
	
	constructor() {
		super()
		
		if (sheZhi.kuaiJieJian[this.kuaiJieJianBianHao]) this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] // 从存储中加载快捷键
		else this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] = moRenKuaiJieJian
		
		wanJiaKongZhi = this
	}
	
	// 处理事件
	chuLi(shiJian) {
		if (shiJian.type == 'keydown') this.jianPanXia(shiJian)
		if (shiJian.type == 'keyup') this.jianPanShang(shiJian)
		if (shiJian.type == 'pointermove') this.zhiZhenYiDong(shiJian)
		if (shiJian.type == 'wheel') this.yuanJin(shiJian)
		if (shiJian.type == 'visibilitychange') this.zhiZhenSuoJianCe(shiJian)
		if (shiJian.type == 'pointerlockchange') this.zhiZhenSuoJianCe(shiJian)
	}

	// 按下键盘按键
	jianPanXia(event) {
		let kjj = this.kuaiJieJian
		
		switch (event.code) {
			case kjj.qianJin.kuaiJieJian:
				this.qian = 1;
				break;
			case kjj.houTui.kuaiJieJian:
				this.hou = -1;
				break;
			case kjj.zuoYi.kuaiJieJian:
				this.zuo = 1;
				break;
			case kjj.youYi.kuaiJieJian:
				this.you = -1;
				break;
			case kjj.jiaSu.kuaiJieJian:
				this.jiaSu = true;
				break;
			case kjj.tiao.kuaiJieJian:
				if (this.keTiao) {
					this.tiao = 1;
					this.keTiao = false
				}
				break;
			case kjj.zhiZhenSuo.kuaiJieJian:
				this.zhiZhenSuoDing(!this.zhiZhenSuo)
				break;
			case kjj.dengKaiGuan.kuaiJieJian:
				wanJia.zhaoMingDeng()
				break;
		}

		let { zuo, you, qian, hou } = this

		if ((zuo || you || qian || hou) && this.yiDongShiJian < 0) this.yiDongShiJian = 0
	}
	// 抬起键盘按键
	jianPanShang(event) {
	let kjj = this.kuaiJieJian
		switch (event.code) {
			case kjj.qianJin.kuaiJieJian:
				this.qian = 0;
				break;
			case kjj.houTui.kuaiJieJian:
				this.hou = 0;
				break;
			case kjj.zuoYi.kuaiJieJian:
				this.zuo = 0;
				break;
			case kjj.youYi.kuaiJieJian:
				this.you = 0;
				break;
			case kjj.jiaSu.kuaiJieJian:
				this.jiaSu = false;
				break;
			case kjj.tiao.kuaiJieJian:
				this.tiao = 0
				this.keTiao = true
				break;
		}

		let { zuo, you, qian, hou } = this

		if (zuo + you + qian + hou  === 0) this.yiDongShiJian = -1
	}
	// 指针锁定切换
	zhiZhenSuoDing(suoDing) {
		let huaBu = huanJing.renderer.domElement

		if (suoDing) {
			huaBu.requestPointerLock() // 解锁后再锁需要大概2秒间隔
			huaBu.focus() // 获取焦点 使可以触发按键事件
		} else {
			document.exitPointerLock()
			// huaBu.blur()
		}
		this.zhiZhenSuoJianCe()
	}
	// 指针锁检测
	zhiZhenSuoJianCe() {
		this.zhiZhenSuo = document.pointerLockElement == huanJing.renderer.domElement
	}
	// 指针移动
	zhiZhenYiDong(event) {
		huanJing.renderer.domElement.focus()

		if (!this.zhiZhenSuo) return
		
		let movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0
		let movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0
		
		let { moXing, xiangJiFuZhu } = wanJia
		
		const eulerZong = new THREE.Euler(0, 0, 0, 'YXZ') // 纵
		const _PI_2 = Math.PI / 2
		const minPolarAngle = 0
		const maxPolarAngle = Math.PI
		let xuanZhuanSuLv = this.xuanZhuanSuLv
		
		eulerZong.setFromQuaternion(xiangJiFuZhu.quaternion)
		eulerZong.x -= movementY * xuanZhuanSuLv
		// 锁定上下90
		eulerZong.x = Math.max(_PI_2 - maxPolarAngle, Math.min(_PI_2 - minPolarAngle, eulerZong.x))
		
		// 移动端
		// eulerHeng.y -= movementY * xuanZhuanSuLv * 10
		// eulerZong.x -= movementX * xuanZhuanSuLv * 10
		
		// 左右旋转
		moXing.rotateY(-movementX * xuanZhuanSuLv) // 角色用euler可能遇到万向锁
		// 上下旋转
		xiangJiFuZhu.quaternion.setFromEuler(eulerZong)
		
		let xuanZhuan = moXing.getWorldQuaternion(new THREE.Quaternion())
		wanJia.sheZhiPengZhuangTi({ xuanZhuan })
	}
	// 镜头拉远拉进，面向：负z
	yuanJin(event) {
		if (!this.zhiZhenSuo) return
		
		let { xiangJiFuZhu } = wanJia
		let chaLiang = 0.5 // 镜头每次移动距离
		event.wheelDelta > 0 ? chaLiang = -chaLiang : chaLiang // 下滚wheelDelta负
		this.juLiZ += chaLiang
		if (this.juLiZ < 0) this.juLiZ = 0
		else if (this.juLiZ > this.zuiYuan) this.juLiZ = this.zuiYuan
	}
	// 更新相机位置
	gengXinXiangJi() {
		let camera = huanJing.camera
		let xiangJiFuZhu = wanJia.xiangJiFuZhu
		xiangJiFuZhu.updateWorldMatrix(true)
		camera.matrix.copy(xiangJiFuZhu.matrixWorld)
		camera.matrix.decompose(camera.position, camera.quaternion, camera.scale)
		camera.translateZ(this.juLiZ)
	}
	// 防止镜头穿模
	fangChuanMo() {
		if (this.juLiZ < 1) return; // 距离1内不启用防穿模

		let { scene, camera } = huanJing
		let { moXing, xiangJiFuZhu } = wanJia
		let chaoXiang = new THREE.Vector3()
		let shi = wanJia.moXing.localToWorld(xiangJiFuZhu.position.clone())
		let zhong = camera.getWorldPosition(new THREE.Vector3())
		chaoXiang.subVectors(zhong, shi)
		chaoXiang.normalize()
		
		let shiJiJuLi = shi.distanceTo(zhong)
		let raycaster = new THREE.Raycaster(shi, chaoXiang, 0, shiJiJuLi)
		raycaster.camera = camera

		let jianCeMoXing = []
		
		scene.traverseVisible(a => {
			if (a.isMesh && !a.userData.chuanMo && !a.isSprite && !a.isInstancedMesh) jianCeMoXing.push(a)
		})

		let xiangJiao = raycaster.intersectObjects(jianCeMoXing, false)

		if (xiangJiao.length > 0) {
			let chaZhi = new THREE.Vector3()
			// worker物体位置更新是异步，避免相机位置偏移，要用本地转换
			chaZhi.lerpVectors(shi, zhong, xiangJiao[0].distance / shiJiJuLi)
			camera.position.copy(chaZhi)
		}
	}
	// 玩家移动
	yiDong() {
		let { zuo, you, qian, hou, tiao, jiaSu } = this
		
		let dongZuo = 'zhan' // 动画动作

		if (zuo || you || qian || hou || tiao) {
			let { moXing, zaiDiMian } = wanJia
			if (!zaiDiMian) return
			
			moXing.updateWorldMatrix(true)
			let qianHou = new THREE.Vector3(0, 0, 1).transformDirection(moXing.matrixWorld)
			let zuoYou = new THREE.Vector3(1, 0, 0).transformDirection(moXing.matrixWorld)
			let shang = new THREE.Vector3(0, 1, 0).transformDirection(moXing.matrixWorld)
			
			qianHou.multiplyScalar(qian + hou)
			zuoYou.multiplyScalar(zuo + you)
			shang.multiplyScalar(tiao)
			
			let zou = new THREE.Vector3()
			let yiSu = this.yiSu
			if (this.yiDongShiJian < this.manSuShiJian) yiSu /= 2 // 慢速
			if (jiaSu) yiSu *= 2 // 加速
			
			zou.addVectors(qianHou, zuoYou).normalize().multiplyScalar(yiSu)
			shang.multiplyScalar(this.tiaoSu)
			
			wanJia.sheZhiPengZhuangTi({ moCa: 0 })
			wanJia.sheZhiJueSe({ zou, tiao: shang })
			
			dongZuo = 'zou'
			
			this.tiao = 0
		} else wanJia.sheZhiPengZhuangTi({ moCa: 4 })
		
		wanJia.dongZuoDongHua(dongZuo)
	}
	
	gengXin(jianGeShi) {
		if (!KongZhi.kongZhiMuBiao.has(this)) return this.guanBi()

		if (this.yiDongShiJian >= 0) this.yiDongShiJian += jianGeShi

		this.yiDong()
		this.gengXinXiangJi()
		this.fangChuanMo()
	}
	
	guanBi() {
		if (this.zhiZhenSuo) this.zhiZhenSuoDing(false)
	}
	
	jiaZai() {
		super.jiaZai()

		this.zhiZhenSuoDing(true)
		// 添加进帧更新
		gengXinJiHe.set(this, this.gengXin.bind(this))
	}
	
	xieZai() {
		super.xieZai()
		
		gengXinJiHe.delete(this)
	}
}

// window.navigator.userAgent.includes('Windows')

// let yaoGanYuanSu = document.getElementById('yao-gan')
// let yiDongBanJing = parseInt(getComputedStyle(document.getElementById('yi-dong')).getPropertyValue('width')) / 2 // 摇杆移动半径
// let yaoGanShiDian = new THREE.Vector2() // 移动端摇杆初始触点
// let yaoGanZhongDian = new THREE.Vector2() // 移动端摇杆初始触点
// let yaoGanXiangLiang = new THREE.Vector2() // 摇杆移动向量
// let yiDongJuLi = 5 // 每秒移动距离 pao 5, zou 2

// 移动端
// if (event.target == yaoGanYuanSu) {
// 	if (event.type == 'pointerdown') {
// 		yaoGanShiDian.set(event.x, event.y)
// 	}
// 	if (event.type == 'pointermove') {
// 		let vec2 = new THREE.Vector2(event.x, event.y)
// 		let juLi = vec2.distanceTo(yaoGanShiDian)
// 		if (juLi > yiDongBanJing) {
// 			let alpha = yiDongBanJing / juLi
// 			// 插值坐标在摇杆半径的圆上
// 			yaoGanZhongDian.lerpVectors(yaoGanShiDian, vec2, alpha)
// 		} else yaoGanZhongDian.copy(vec2)
// 		yaoGanXiangLiang.subVectors(yaoGanZhongDian, yaoGanShiDian)
// 		yaoGanYuanSu.style.top = `${yiDongBanJing - yaoGanXiangLiang.x}px`
// 		yaoGanYuanSu.style.left = `${yiDongBanJing + yaoGanXiangLiang.y}px`
// 	}
// 	if (event.type == 'pointerup') {
// 		yaoGanXiangLiang.set(0, 0)
// 		yaoGanYuanSu.style.top = `${yiDongBanJing}px`
// 		yaoGanYuanSu.style.left = `${yiDongBanJing}px`
// 	}
// }

// if (gongYou.yiDongDuan) {
// 		// 移动端
// 		chaoXiang.z = yaoGanXiangLiang.x
// 		chaoXiang.x = -yaoGanXiangLiang.y
// 		chaoXiang.normalize()
// 		suDu.add(chaoXiang.multiplyScalar(yiDongJuLi))
// 		suDu.applyQuaternion(kongZhiWuTi.moXing.quaternion)
// 	}

export {
	WanJiaKongZhi,
	wanJiaKongZhi
};